/*
 *		source/folderview/folderview.js
 */

/* Tegi's Commander - A file manager for Palm WebOS
 * Copyright (C) 2011 Timo Tegtmeier
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 3
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

enyo.kind({
	name:		"FolderViewToolbar",
	kind:		"Toolbar",

	published:	{
		isLeft:			false,
		showGotoFolder:	false,
		showCreateFile:	false,
		canGoUp:		true
	},

	events:		{
		onGotoFolder:	"",
		onGoFolderUp:	"",
		onCreateFolder:	"",
		onCreateFile:	""
	},

	isLeftChanged: function() {
		this.destroyControls();
		var components = [{
			name:		"folderUpButton",
			kind:		"ToolButton",
			icon:		"images/folderup.png",
			onclick:	"doGoFolderUp"
		}, {
			name:		"gotoFolderButton",
			kind:		"ToolButton",
			icon:		"images/foldergoto.png",
			onclick:	"doGotoFolder",
			showing:	this.showGotoFolder
		}, {
			kind:		"Spacer"
		}, {
			kind:		"ToolButton",
			icon:		"images/folderadd.png",
			onclick:	"doCreateFolder"
		}, {
			name:		"createFileButton",
			kind:		"ToolButton",
			icon:		"images/add.png",
			onclick:	"doCreateFile",
			showing:	this.showCreateFile
		}, {
			kind:		"Spacer"
		}, {
			name:		"switchButton",
			kind:		"ToolButton",
			icon:		"images/switch.png",
			onclick:	"doSwitch",
			showing:	this.isLeft
		}, {
			kind:		"GrabButton",
			showing:	!this.isLeft
		}];

		if(!this.isLeft) {
			components.reverse();
		}
		this.createComponents(components);
	},

	showGotoFolderChanged: function() {
		this.$.gotoFolderButton.setShowing(this.showGotoFolder);
	},

	showCreateFileChanged: function() {
		this.$.createFileButton.setShowing(this.showCreateFile);
	},

	canGoUpChanged: function() {
		if(this.$.folderUpButton) {
			this.$.folderUpButton.setDisabled(!this.canGoUp);
		}
	}
});

enyo.kind({
	name:		"FolderView",
	kind:		"SlidingView",
	LayoutKind:	"VFlexLayout",

	published:	{
		path:				"",
		isLeft:				true,
		showGotoFolder:		false,
		showCreateFile:		true,
		showHiddenFiles:	false
	},

	events:		{
		onError:		"",
		onOpenFile:		"",
		onEditFile:		"",
		onCopyFile:		"",
		onMoveFile:		"",
		onIsEditable:	"",
		onIsImage:		"",
		onSwitch:		""
	},

	noPunt:			false,
	files:			[],
	scrollItem:		null,
	scrollOffset:	0,

	components:	[{
		name:		"header",
		kind:		"PageHeader",
		className:	"enyo-toolbar-light",
		layoutKind:	"HFlexLayout",
		components:	[{
			name:		"title",
			className:	"title ellipsis",
			flex:		1
		}]
	}, {
		kind:		"VirtualList",
		name:		"list",
		flex:		1,
		onSetupRow:	"setupRow",
		components:	[{
			name:		"item",
			kind:		"SwipeableItem",
			onConfirm:	"deleteFile",
			onclick:	"openFile",
			components:	[{
				kind:	"HFlexBox",
				align:	"center",
				components: [{
					name:		"fileIcon",
					kind:		"Image",
					className:	"file-icon"
				}, {
					flex:		1,
					components:	[{
						name:		"fileEntry",
						className:	"file-name ellipsis"
					}, {
						name:		"fileSize",
						className:	"file-info ellipsis"
					}, {
						name:		"fileDate",
						className:	"file-info ellipsis"
					}]
				}, {
					kind:		"IconButton",
					icon:		"images/info-icon.png",
					onclick:	"infoClicked"
				}]
			}]
		}]
	}, {
		name:			"toolbar",
		kind:			"FolderViewToolbar",
		onGotoFolder:	"gotoFolder",
		onGoFolderUp:	"goFolderUp",
		onCreateFolder:	"createFolder",
		onCreateFile:	"createFile"
	}, {
		name:		"fileMenu",
		kind:		"EnhancedMenu"
	}, {
		kind: 		"ModalDialog",
		name:		"inputDialog",
		lazy:		false,
		components: [{
			name:		"inputMessage",
			style:		"margin: 25px"
		}, {
			kind:		"RowGroup",
			components: [{
				name:				"input",
				kind:				"Input",
				spellcheck: 		false,
				autocorrect:		false,
				autoCapitalize:		"lowercase",
				autoEmoticons:		false,
				autoLinking:		false,
				autoWordComplete:	false,
				selectAllOnFocus:	true
			}]
		}, {
			kind: 	"HFlexBox",
			pack: "center",
			components: [{
				name:		"dialogOKButton",
	            kind:		"Button",
				caption:	$L("OK"),
				className:	"enyo-button-affirmative",
				flex:		1
			}, {
				kind:		"Button",
				caption:	$L("Cancel"),
				className:	"enyo-button-negative",
				onclick:	"closeDialog",
				flex:		1
			}]
		}]
	}, {
		name:		"fileService",
		kind:		"PalmService",
		service:	"palm://com.tegistuff.app.commander.service/"
	}],

	//
	// Dialog handling
	//

	closeDialog: function() {
		this.$.inputDialog.close();
	},

	//
	// List handling
	//

	getIcon: function(file) {
		var icon = "file.png";
		if(file.isDir) {
			icon = "folder.png";
		} else if(file.isSpecial) {
			icon = "special.png";
		} else if(/.*\.js/.test(file.name) || /.*\.json/.test(file.name)) {
			icon = "js.png";
		} else if(/.*\.txt/.test(file.name)) {
			icon = "txt.png";
		} else if(/.*\.doc/.test(file.name) || /.*\.docx/.test(file.name) || /.*\.odt/.test(file.name)) {
			icon = "doc.png";
		} else if(/.*\.xls/.test(file.name) || /.*\.xlsx/.test(file.name) || /.*\.ods/.test(file.name)) {
			icon = "xls.png";
		} else if(/.*\.ppt/.test(file.name) || /.*\.pptx/.test(file.name) || /.*\.odp/.test(file.name)) {
			icon = "ppt.png";
		} else if(/.*\.pdf/.test(file.name)) {
			icon = "pdf.png";
		} else if(this.doIsImage(file.name)) {
			icon = "image.png";
		} else if(/.*\.mp3/.test(file.name) || /.*\.ogg/.test(file.name) || /.*\.wav/.test(file.name)) {
			icon = "audio.png";
		} else if(/.*\.mpg/.test(file.name) || /.*\.mpeg/.test(file.name) || /.*\.mp4/.test(file.name) || /.*\.avi/.test(file.name)) {
			icon = "video.png";
		}
		return "images/" + icon;
	},

	getFileSize: function(file) {
		if(file.isDir) {
			return $L("Directory");
		} else {
			var size = file.size;
			var sizeUnit = $L("Byte");
			if(size > 1024) {
				size /= 1024;
				sizeUnit = $L("KByte");
			}
			if(size > 1024) {
				size /= 1024;
				sizeUnit = $L("MByte");
			}
			if(size > 1024) {
				size /= 1024;
				sizeUnit = $L("GByte");
			}
			return this.numberFormatter.format(size) + ' ' + sizeUnit;
		}
	},

	getFileTimes: function(file) {
		return enyo.macroize($L("Last Change: {$mtime}, Created: {$ctime}"), {
			ctime:	this.datetimeFormatter.format(new Date(file.ctime)),
			mtime:	this.datetimeFormatter.format(new Date(file.mtime))
		});
	},

	setupRow: function(sender, rowIndex) {
		var index = rowIndex + this.scrollOffset;
		if((index < 0) || (index >= this.files.length)) {
			return false;
		}

		var file = this.files[index];

		this.$.fileIcon.setSrc(this.getIcon(file));
		this.$.fileEntry.setContent(file.name);
		this.$.fileSize.setContent(this.getFileSize(file));
		this.$.fileDate.setContent(this.getFileTimes(file));

		return true;
	},

	deleteFile: function(sender, rowIndex) {
		this.menuIndex = rowIndex + this.scrollOffset;
		this.$.fileService.call({
			path:		this.joinPath(this.files[this.menuIndex].name)
		}, {
			method:		"delete",
			onSuccess:	"deleteFileSuccess",
			onFailure:	"errorHandler"
		});
	},

	deleteFileSuccess: function() {
		this.files.splice(this.menuIndex);
		this.$.list.refresh();
	},

	deleteFileFailed: function() {
		this.doError($L("Deleting the selected file failed."));
	},

	openFile: function(sender, event) {
		var file = this.files[event.rowIndex + this.scrollOffset];
		if(!file.isSpecial) {
			var absPath = this.joinPath(file.name);
			if(file.isDir) {
				this.setPath(absPath);
			} else {
				this.doOpenFile(absPath);
			}
		}
	},

	infoClicked: function(sender, event) {
		this.menuIndex = event.rowIndex + this.scrollOffset;
		this.$.fileMenu.setItems([{
			caption:	$L("Open"),
			onclick:	"openFileByMenu"
		}, {
			caption:	$L("Copy"),
			onclick:	"copyFileByMenu"
		}, {
			caption:	$L("Move"),
			onclick:	"moveFileByMenu"
		}, {
			caption:	$L("Edit"),
			onclick:	"editFileByMenu",
			showing:	this.doIsEditable(this.files[this.menuIndex].name)
		}, {
			caption:	$L("Rename"),
			onclick:	"renameFileByMenu"
		}, {
			caption:	$L("Delete"),
			onclick:	"deleteFileByMenu"
		}]);
		this.$.fileMenu.openAtEvent(event);
		return true;
	},

	//
	// Menu handling
	//

	openFileByMenu: function() {
		this.openFile(this, {
			rowIndex: this.menuIndex
		});
	},

	editFileByMenu: function() {
		this.doEditFile(this.joinPath(this.files[this.menuIndex].name));
	},

	copyFileByMenu: function() {
		this.doCopyFile(this.files[this.menuIndex].name);
	},

	moveFileByMenu: function() {
		this.doMoveFile(this.files[this.menuIndex].name);
	},

	renameFileByMenu: function() {
		this.$.inputMessage.setContent(enyo.macroize($L("Please enter a new name for '{$file}'."), {
			file: this.files[this.menuIndex].name
		}));
		this.$.input.setHint($L("New file name"));
		this.$.input.setValue(this.files[this.menuIndex].name);
		this.$.dialogOKButton.onclick = "doRenameFile";
		this.$.inputDialog.openAtCenter();
	},

	deleteFileByMenu: function() {
		this.deleteFile(this, this.menuIndex);
	},

	doRenameFile: function() {
		this.$.inputDialog.close();

		var oldFileName = this.files[this.menuIndex].name;
		var newFileName = this.$.input.getValue();
		this.files[this.menuIndex].name = newFileName;

		if(newFileName) {
			this.$.fileService.call({
				fromPath:	this.joinPath(oldFileName),
				toPath:		this.joinPath(newFileName)
			}, {
				method:		"rename",
				onSuccess:	"refreshFileList",
				onFailure:	"errorHandler"
			});
		}
	},

	renameFileSuccess: function() {
		this.$.list.refresh();
	},

	renameFileFailed: function() {
		this.doError($L("Renaming the selected file failed."));
		this.refreshFileList();
	},

	//
	// Service functions
	//

	errorHandler: function() {
		this.doError();
	},

	refreshFileList: function() {
		this.$.fileService.call({
			path:				this.path,
			showHiddenFiles:	this.showHiddenFiles
		}, {
			method:		"scandir",
			onSuccess:	"scanDirSucceeded",
			onFailure:	"scanDirFailed"
		});
	},

	scanDirSucceeded: function(sender, response) {
		this.files = response.files;
		this.files.sort(function(a, b) {
			if(a.isDir != b.isDir) {
				return a.isDir ? -1 : 1;
			}
			if(a.isSpecial != b.isSpecial) {
				return a.isSpecial ? -1 : 1;
			}
			return (a.name == b.name ) ? 0 : ((a.name > b.name) ? 1 : -1);
		});
		this.scrollToItem();
	},

	scanDirFailed: function(sender, response) {
		// The service might not be running. In this case, silently
		// re-do the operation.
		if(response.errorText && response.errorText.match("not running")) {
			this.refreshFileList();
			return;
		}

		var message = enyo.macroize($L("Unable to scan directory '{$path}'. Switching back to '{$oldPath}'."), {
			path: 		this.path,
			oldPath:	this.oldPath
		});
		this.doError(message);
		this.setPath(this.oldPath);
	},

	//
	// Toolbar handling
	//

	goFolderUp: function() {
		var newPath = this.joinPath('..');
		if(newPath != this.path) {
			this.scrollItem = this.path.replace(/^.*\/([^\/]*)$/, "$1");
			this.setPath(newPath);
		}
	},

	createFolder: function() {
		this.$.inputMessage.setContent($L("Please enter a name for the directory."));
		this.$.input.setHint($L("Name of the directory"));
		this.$.input.setValue("New directory");
		this.$.input.forceFocus();
		this.$.dialogOKButton.onclick = "doCreateFolder";
		this.$.inputDialog.openAtCenter();
	},

	doCreateFolder: function() {
		this.$.inputDialog.close();
		var newFileName = this.$.input.getValue();
		if(newFileName) {
			this.$.fileService.call({
				path:		this.joinPath(newFileName)
			}, {
				method:		"makedir",
				onSuccess:	"refreshFileList",
				onFailure:	"createFolderFailed"
			});
		}
	},

	createFolderFailed: function() {
		this.doError($L("Creating folder failed."));
	},

	gotoFolder: function() {
		this.$.inputMessage.setContent($L("Please enter the path to change to."));
		this.$.input.setHint($L("Path"));
		this.$.input.setValue(this.path);
		this.$.input.forceFocus();
		this.$.dialogOKButton.onclick = "doGotoFolder";
		this.$.inputDialog.openAtCenter();
	},

	doGotoFolder: function() {
		this.$.inputDialog.close();
		var newPath = this.$.input.getValue();
		if(newPath) {
			this.setPath(newPath);
		}
	},

	createFile: function() {
		this.$.inputMessage.setContent($L("Please enter file name to create."));
		this.$.input.setHint($L("File name"));
		this.$.input.setValue($L("New File"));
		this.$.input.forceFocus();
		this.$.dialogOKButton.onclick = "doCreateFile";
		this.$.inputDialog.openAtCenter();
	},

	doCreateFile: function() {
		this.$.inputDialog.close();
		var fileName = this.$.input.getValue();
		if(fileName) {
			this.$.fileService.call({
				path:		this.joinPath(fileName)
			}, {
				method:		"touch",
				onSuccess:	"refreshFileList",
				onFailure:	"createFileFailed"
			});
		}
	},

	createFileFailed: function() {
		this.doError($L("Creating file failed."));
	},


	//
	// Helper functions
	//

	joinPath: function(p) {
		if(p == '..') {
			if(this.path == '/') {
				return this.path;
			} else {
				var path = this.path.replace(/^(.*)\/[^\/]*$/, "$1");
				if(path == "") {
					return "/";
				}
				return path;
			}
		} else {
			if(/^.*\/$/.test(this.path)) {
				return this.path + p;
			} else {
				return this.path + '/' + p;
			}
		}
	},

	scrollToItem: function() {
		if(this.noPunt) {
			this.$.list.refresh();
		} else {
			var pageSize = this.$.list.getPageSize() - 2;
			this.scrollOffset = 0;
			if(this.scrollItem && (pageSize < this.files.length)) {
				for(var i = 0; i < this.files.length; i++) {
					if(this.files[i].name == this.scrollItem) {
						this.scrollOffset = i;
						if(this.scrollOffset + pageSize >= this.files.length) {
							this.scrollOffset = this.files.length - pageSize;
						}
						break;
					}
				}
			}
			this.scrollItem = null;
			this.$.list.punt();
		}
		this.noPunt = false;
	},

	//
	// Properties
	//

	pathChanged: function(oldPath) {
		this.oldPath = (!oldPath || (oldPath.length <= 0)) ? "/" : oldPath;
		if(!/^\/media\/internal.*$/.test(this.path)) {
			this.path = "/media/internal";
		}
		if(this.path.length > 0) {
			this.refreshFileList();
			this.$.title.setContent(this.path);
		}
		this.$.toolbar.setCanGoUp(this.path != "/media/internal");
	},

	isLeftChanged: function() {
		this.$.toolbar.setIsLeft(this.isLeft);
	},

	showGotoFolderChanged: function() {
		this.$.toolbar.setShowGotoFolder(this.showGotoFolder);
	},

	showCreateFileChanged: function() {
		this.$.toolbar.setShowCreateFile(this.showCreateFile);
	},

	//
	// Initilization
	//

	create: function() {
		this.inherited(arguments);

		this.isLeftChanged();

		this.datetimeFormatter = new enyo.g11n.DateFmt({
			format:	"medium"
		});
		this.numberFormatter = new enyo.g11n.NumberFmt({
			style:			"number",
			fractionDigits:	2
		});
	}
});
